import json

from flask import Flask, render_template, request
from flask_cors import CORS
from flask_socketio import SocketIO, emit, join_room, leave_room

from common import *

app = Flask(__name__,static_folder = '../dist/static',template_folder = '../dist')
app.config['SECRET_KEY'] = 'i-yi-yi-1182'
socketio = SocketIO(app)
CORS(app, resources={r'/*': {'origins': '*'}}, supports_credentials = True)
gameDict = {} # 这个玩意应该写在class Game里吧？

@app.route('/api/login', methods = ['POST'])
def login():
    dictionary = request.form.to_dict()
    if checkRequest(dictionary):
        return Player.login(dictionary)
    return json.dumps({'succeed': False, 'msg': 'Security authentication failed'}, ensure_ascii = False)

@app.route('/api/register', methods = ['POST'])
def register():
    dictionary = request.form.to_dict()
    if checkRequest(dictionary):
        return Player.register(dictionary)
    return json.dumps({'succeed': False, 'msg': 'Security authentication failed'}, ensure_ascii = False)

@app.route('/api/getUserInfo', methods = ['POST'])
def getUserInfo():
    return Player.getInfo(request.form.to_dict())

@app.route('/api/create', methods = ['POST'])
def create():
    return Hall.create(request.form.to_dict())

@app.route('/api/enter', methods = ['POST'])
def enter():
    return Hall.enter(request.form.to_dict())

@app.route('/api/getAllGame', methods = ['POST'])
def getAllGame():
    return Hall.getAllGame()

@app.route('/api/click', methods = ['POST'])
def pickChess():
    data = request.form.to_dict()
    b = gameDict[int(data['roomId'])].getBoard()
    res = b.click(int(data['control']), [int(data['x']), int(data['y'])])
    return json.dumps(res, ensure_ascii = False)

@app.route('/api/upload', methods = ['POST'])
def upload():
    return Player.uploadHead(request.form.to_dict())

@app.route('/', defaults = {'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    return render_template('index.html', async_mode=socketio.async_mode)

@socketio.on('connect', namespace='/wsio')
def connect():
    emit('connect', {'data': 'Connected'})

@socketio.on('reconnect', namespace='/wsio')
def reconnect(data): #重新连接事件
    print('\t=>', end='\t')
    print(data)
    emit('reconnect', {'reconnect': True})

@socketio.on('chat', namespace='/wsio')
def chat(data): #房间内聊天
    cookie = parseCookie(request)
    roomId = cookie['room']['roomId']
    emit('chat', {'name': cookie['user']['name'], 'textInput': data['msg']}, room = roomId)

@socketio.on('enter', namespace='/wsio')
def enter(data): #加入房间
    cookie = parseCookie(request)
    join_room(data['roomId'])
    emit('updateHall', {}, broadcast=True)
    emit('enter', {'uid': cookie['user']['id']}, room = data['roomId'])

@socketio.on('leave', namespace='/wsio')
def leave(data): #离开房间
    cookie = parseCookie(request)
    if Hall.leave(cookie['user']['id'], data['roomId']): #同步到数据库中
        gameDict[data['roomId']] = None #将房间置为None
    leave_room(data['roomId'])
    emit('leave', {'data': 'Leaved'}, room = data['roomId'])

@socketio.on('start', namespace='/wsio')
def start(data): #开始游戏
    roomId = data['roomId']
    if not gameDict[roomId].isStart:
        if gameDict.get(roomId, None) is None:
            gameDict[roomId] = Game()
        gameDict[roomId].isStart = True
        b = gameDict[roomId].reset()
        emit('gameStart', {'p0': 1, 'p1': 0, 'board': flatChessList(b.getSimple())}, room = roomId)

def handle(data): # 拆complete函数
    side = data['side']
    roomId = data['roomId']
    g = gameDict[roomId]
    clicked = [int(data['x']), int(data['y'])]
    selected = g.getBoard().getSelect()
    g.pushHistory(selected, clicked) # 添加历史信息(ai使用)
    nextData = g.next() # 我把else中的函数拿出来先执行了
    allData = g.getBoard().click(1, clicked)
    if 'status' in allData and int(allData['status']) == 4:
        emit('overGame', {'winner': 1 - side}, room = roomId)
        gameDict[roomId].overGame(roomId, 1 - side, False)
    else:
        emit('complete', nextData, room = roomId)
    p0, p1 = g.getPlayer()
    res = {'side': 1 - side,'name': allData['name'],'status': allData['status'],'start': selected,'finish': clicked}
    emit('moveTo', res, room = roomId)
    if ('refresh' in nextData and nextData['refresh']) or ('refresh' in allData and allData['refresh']):
        # 应该再发送一个特效响应事件
        emit('updateGame', {'board': flatChessList(g.getBoard().getSimple()), 'p0': p0, 'p1': p1}, room = roomId)

@socketio.on('complete', namespace='/wsio')
def complete(data): #完成行棋
    roomId = data['roomId']
    side = int(data['side'])
    handle(data)
    if data['robot']: # 这里还需要执行一遍行棋
        g = gameDict[roomId]
        l = ChessAI(g.getBoard(), g.getHistory(), 1 - side)
        ai = l.get_result()
        if ai is not None:
            g.getBoard().click(1, [ai[0], ai[1]]) # 先选中
            aiData = {'roomId': roomId, 'x': ai[2], 'y': ai[3], 'side': 1 - side}
            handle(aiData)
        else:
            print('ai被将死了')
            g.overGame(roomId, 1 - side, False)
            emit('overGame', {'winner': 1 - side}, room = roomId)

@socketio.on('recovery', namespace='/wsio')
def recovery(data):
    roomId = data['roomId']
    if gameDict.get(roomId, None) is not None and gameDict[roomId].isStart:
        g = gameDict[roomId]
        p0, p1 = g.getPlayer()
        emit('updateGame', {'board': flatChessList(g.getBoard().getSimple()), 'p0': p0, 'p1': p1}, broadcast=False)

@socketio.on('prepare', namespace='/wsio')
def prepare(data):
    roomId = data['roomId']
    side = data['side']
    g = gameDict.get(roomId, None)
    if g is None:
        gameDict[roomId] = g = Game()
    if 'sk' in data:
        g.sk[str(side)] = data['sk']
    emit('prepare', {'side': side}, room = roomId)

@socketio.on('draw', namespace='/wsio')
def draw(data):
    roomId = data['roomId'] # cookie不能接收room信息
    side = data['side']
    if 'offer' in data and data['offer']:
        emit('draw', {'side': side}, room = roomId)
    elif data['accept']: # 和棋
        gameDict[roomId].overGame(roomId, 1 - side, True)
        emit('draw', {'succeed': True, 'side': side}, room = roomId)
    else:
        emit('draw', {'succeed': False, 'side': side}, room = roomId)

@socketio.on('defeat', namespace='/wsio')
def defeat(data):
    roomId = data['roomId']
    side = int(data['side'])
    gameDict[roomId].overGame(roomId, 1 - side, False)
    emit('overGame', {'winner': 1 - side}, room = roomId)

@socketio.on('repentance', namespace='/wsio')
def repentance(data):
    roomId = data['roomId']
    side = int(data['side'])
    if 'offer' in data and data['offer']:
        emit('repentance', {'side': side}, room = roomId)
    elif data['accept']:
        res = gameDict[roomId].repentance()
        emit('updateGame', res, room = roomId)
        emit('repentance', {'succeed': True, 'side': side}, room = roomId)
    else:
        emit('repentance', {'succeed': False, 'side': side}, room = roomId)

if __name__ == '__main__':
    load_dict = {}
    with open('../dist/static/config.json','r') as load_file:
        load_dict = json.load(load_file)
        print(load_dict)
    socketio.run(app, debug=True, host='127.0.0.1', port=5000)
